package org.example.rmsmsapi.log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Enumeration;

/**
 * 请求日志切面，用于记录HTTP请求和响应信息
 * @zhoubin
 */
@Aspect
@Component
public class RequestLogAspect {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    // 记录请求开始时间
    private ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * 定义切入点，拦截所有控制器方法
     */
    @Pointcut("execution(* org.example.rmsmsapi.controller..*.*(..))")
    public void controllerPointcut() {}

    /**
     * 前置通知，在方法执行前执行
     * @param joinPoint 连接点
     */
    @Before("controllerPointcut()")
    public void before(JoinPoint joinPoint) {
        startTime.set(System.currentTimeMillis());
        
        // 获取当前请求
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            
            // 记录请求信息
            logger.debug("========================================== 请求开始 ==========================================");
            logger.info("请求路径: {}", request.getRequestURL().toString());
            logger.info("请求方法: {}", request.getMethod());
            logger.info("请求IP: {}", request.getRemoteAddr());
            logger.info("请求类方法: {}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
            logger.info("请求参数: {}", Arrays.toString(joinPoint.getArgs()));
            
            // 记录请求头
            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                logger.debug("请求头 - {}: {}", headerName, request.getHeader(headerName));
            }
        }
    }

    /**
     * 后置通知，在方法执行后执行（无论是否发生异常）
     */
    @After("controllerPointcut()")
    public void after() {
        logger.info("========================================== 请求结束 ==========================================");
    }

    /**
     * 返回通知，在方法正常返回后执行
     * @param result 返回结果
     */
    @AfterReturning(returning = "result", pointcut = "controllerPointcut()")
    public void afterReturning(Object result) {
        // 记录响应结果
        logger.info("响应结果: {}", result);
        
        // 记录请求处理时间
        logger.info("请求处理时间: {}ms", System.currentTimeMillis() - startTime.get());
        startTime.remove();
    }

    /**
     * 异常通知，在方法抛出异常后执行
     * @param ex 异常
     */
    @AfterThrowing(pointcut = "controllerPointcut()", throwing = "ex")
    public void afterThrowing(Exception ex) {
        // 记录异常信息
        logger.error("请求处理过程中发生异常", ex);
        
        // 记录请求处理时间
        logger.info("请求处理时间: {}ms", System.currentTimeMillis() - startTime.get());
        startTime.remove();
    }
}
    